<template>
  <div class="map-box box-shadow">
    <!--   地图   -->
    <div id="mapboxgl-box"></div>
  </div>
  <div class="form-box box-shadow">
    <div class="set-header">
      <span>所选单元-{{cellInfo.cellName}}</span>
    </div>
    <div class="set-form">
      <a-form
          v-if="compactionType == KindEnum.compaction_i"
          :labelCol="{style: 'width: 120px'}"
          :wrapperCol="{span:24}"
          layout="inline">
        <span>冲碾标准</span>
        <a-form-item label="最低碾压遍数">
          <a-input-number v-model:value="norm.impact.timesMin"/>
        </a-form-item>
        <a-form-item label="最高碾压遍数">
          <a-input-number v-model:value="norm.impact.timesMax"/>
        </a-form-item>
        <a-form-item label="最低碾压速度">
          <a-input-number v-model:value="norm.impact.speedMin"/>
        </a-form-item>
        <a-form-item label="最高碾压速度">
          <a-input-number v-model:value="norm.impact.speedMax"/>
        </a-form-item>
        <a-form-item>
          <div style="width:100px;height:40px"></div>
        </a-form-item>
        <a-form-item style="float:right;margin:4px 16px">
          <a-button @click="setNorm" type="primary">保存</a-button>
        </a-form-item>
      </a-form>
      <div
        class="cv-norm-box"
        v-if="compactionType == KindEnum.compaction_v || compactionType==KindEnum.pavComp">
        <a-table
            :data-source="norm.vibration"
            :scroll="{y:'200px'}"
            :pagination="false">
          <a-table-column
              title="顺序"
              data-index="order"/>
          <a-table-column
              title="施工类型"
              data-index="kind">
            <template #default="{text,record,index}">
              <a-select
                v-model:value="record.kind">
                <a-select-option
                    v-for="compaction in CompactionDict.dict"
                    :key="compaction.key" :value="compaction.key">
                  {{compaction.value}}
                </a-select-option>
              </a-select>
            </template>
          </a-table-column>
          <a-table-column
              title="最低遍数"
              data-index="timesMin">
            <template #default="{text,record}">
              <a-input-number v-model:value="record.timesMin"/>
            </template>
          </a-table-column>
          <a-table-column
              title="最高遍数"
              data-index="timesMax">
            <template #default="{text,record}">
              <a-input-number v-model:value="record.timesMax"/>
            </template>
          </a-table-column>
          <a-table-column
              title="最小速度(km/h)"
              data-index="speedMin">
            <template #default="{text,record}">
              <a-input-number v-model:value="record.speedMin"/>
            </template>
          </a-table-column>
          <a-table-column
              title="最大速度(km/h)"
              data-index="speedMax">
            <template #default="{text,record}">
              <a-input-number v-model:value="record.speedMax"/>
            </template>
          </a-table-column>
          <a-table-column
              title="删除"
              width="80px">
            <template #default="{text,record,index}">
              <div class="table-icon-box">
                <div @click="removeNorm(index)" style="width:100%">
                  <DeleteOutlined/>
                </div>
              </div>
            </template>
          </a-table-column>
        </a-table>
        <div class="button-box">
          <a-button @click="addVNorm" type="primary">新增</a-button>
          <a-button @click="setNorm" type="primary">保存</a-button>
        </div>
      </div>


      <span>单元范围设置</span>
      <a-form
          :labelCol="{style: 'width: 120px'}"
          :wrapperCol="{span:24}"
          layout="inline">
        <a-form-item label="坐标系">
          <a-select
              v-model:value="coordinateType">
            <a-select-option
                v-for="coordinate in coordinateDict.dict"
                :key="coordinate.key" :value="coordinate.key">
              {{coordinate.value}}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item class="button-box">
          <a-button @click="openFileModal('uploadBorderFile')" type="primary">导入
            <input
                id="uploadBorderFile"
                @change="readBorderFile(cellInfo.cellId)"
                accept=".txt"
                style="position:absolute;width:0;height:0;opacity:0"
                type="file"
            />
          </a-button>
          <a-button @click="getBorder(coordinateType,cellInfo.cellId,()=>{showBorderModal = true})" :disabled="cellInfo.cellId<0" type="primary">显示</a-button>
        </a-form-item>
      </a-form>
    </div>
  </div>
  <SModal
      title="边界坐标"
      :width="372"
      :height="300"
      :isShow="showBorderModal"
      @closed="() => {showBorderModal = false}">
    <div class="add-modal-box">
      <a-table
          style="flex: 1"
          :data-source="coordinateType==1?abBorder:wgsBorder"
          :bordered="false"
          :scroll="{y: '180px' }"
          :pagination="false"
          :locale="{ emptyText: '暂无数据' }"
          :rowKey="(record) => record.lon">
        <a-table-column :title="coordinateType==1?'P坐标':'经度'" data-index="lon">
          <template #default="{text}">
            {{ text.toFixed(6) }}
          </template>
        </a-table-column>
        <a-table-column :title="coordinateType==1?'H坐标':'纬度'" data-index="lat">
          <template #default="{text}">
            {{ text.toFixed(6) }}
          </template>
        </a-table-column>
      </a-table>
    </div>
  </SModal>
</template>

<script lang="ts">
import {defineComponent, onBeforeUnmount, onMounted, reactive, ref, toRefs, watch} from "vue"
import coordinateDict from "@/dicts/coordinateDict"
import mapboxgl,{AnyLayer,Sources} from "mapbox-gl"
import redLine from "@/assets/data/redLine"
import "mapbox-gl/dist/mapbox-gl.css"
import {message} from "ant-design-vue"
import SModal from "@/components/SModal/index.vue"
import KindEnum from "@/enums/kindEnum"
import CompactionDict from "@/dicts/compactionDict"
import config from "@/config/index"
import axios from "@/utils/axios"
import {EditOutlined,DeleteOutlined} from '@ant-design/icons-vue'
import qs from "qs";

interface MapLayerRequestInfo{
  craft:string|null
  cellId:number|null
  type:string|null
}

interface VrNorm{
  order:number,
  kind:number|null,
  timesMin: number|null,
  timesMax: number|null,
  speedMin: number|null,
  speedMax:  number|null
}

class Norm{
  cellId = -1
  vibration = new Array<VrNorm>()
  impact = {
    timesMin: <number|null>null,
    timesMax: <number|null>null,
    speedMin: <number|null>null,
    speedMax: <number|null>null
  }
}

class CoordinateForm{
  cellId:number = -1
  count:number = 0
  first = new Array<number>()
  second = new Array<number>()
}

export default defineComponent({
  setup(props){
    const coordinateTypeFormState = ref(new CoordinateForm())
    const border:any = reactive({
      abBorder:[],
      wgsBorder:[]
    })
    const showBorderModal = ref(false)
    const compactionType =ref(KindEnum.compaction_v)
    const coordinateType = ref(1)

    const norm = ref(new Norm())

    let maps:any
    const initMap = ()=>{
      mapboxgl.accessToken = config.map.accessToken
      let mapSource:Sources = {
        google: {
          type: "raster",
          tiles: [config.map.baseLayer1URL,config.map.baseLayer2URL,config.map.baseLayer3URL],
          tileSize: 256,
        },
      }
      let layers:AnyLayer[] = [
        {
          id: "google-tiles1",
          type: "raster",
          source: "google",
        },
      ]
      maps = {
        map:new mapboxgl.Map({
          container: "mapboxgl-box",
          style: {
            version: 8,
            sources: mapSource,
            layers: layers,
          },
          minZoom: 5,
          center: config.map.center,
          zoom: 13,
          attributionControl: false
        }),
        sourceList: new Set<string>(),
        LayerList: new Set<string>()
      }

      maps.map.on("load",()=>{
        maps.map.addLayer({
          id: "air",
          type: "raster",
          source: {
            type: "raster",
            tiles: [config.map.airUrl],
          },
        })
        maps.map.addSource("readLineSource",{type:"geojson",data:redLine})
        maps.map.addLayer({
          id: "readLineLayer",
          type: "line",
          source: "readLineSource",
          layout: {},
          paint: {
            "line-color":"#ff0000",
            "line-width":2,
            "line-opacity":1
          },
        })
      })
    }

    const addVNorm = ()=>{
      if(norm.value.vibration.length==5){
        message.info("最多设置五条")
      }else{
        norm.value.vibration.push({
          order:norm.value.vibration.length,
          kind:0,
          timesMin:null,
          timesMax:null,
          speedMin:null,
          speedMax:null
        })
      }
    }

    const removeNorm = (index:number)=>{
      // 移除当前列,遍历数据重新赋值order
      norm.value.vibration.splice(index,1)
      for(let i = 0;i<norm.value.vibration.length;i++){
        norm.value.vibration[i].order = i
      }
    }

    const getNorm = (cellId:number)=>{
      axios.post("/comp/findCellParameterByCellId",{cellId:cellId}).then((res:any)=>{
        norm.value = new Norm()
        norm.value.cellId = cellId
        if(res.success && res.data){
          if(res.data.vibration) norm.value.vibration = res.data.vibration
          if(res.data.impact) norm.value.impact = res.data.impact
        }else if(res.success && !res.data){
          message.info("暂未录入标准")
        }else{
          message.info("获取标准失败")
        }
      })
    }

    const setNorm = ()=>{
      axios.post("/comp/saveCellParameter",norm.value).then((res:any)=>{
        if(res.success){
          message.info("保存成功")
        }else{
          message.info("保存失败")
        }
      })
    }

    const openFileModal = (id:string)=>{
      document.getElementById(id)?.click();
    }

    // 添加边界图层
    const addBorderLayer = (id:number)=>{
      if(!maps.map) return
      let layerInfo:MapLayerRequestInfo = {
        cellId:id,
        craft:"HaErBin-NY",
        type:"border"
      }
      if(maps.map.getLayer(`${layerInfo.type}`)) maps.map.removeLayer(`${layerInfo.type}`)
      if(maps.map.getSource(`${layerInfo.type}`)) maps.map.removeSource(`${layerInfo.type}`)

      maps.map.addSource(`${layerInfo.type}`,{
        type: "raster",
        scheme:"tms",
        tiles: [
          `${config.map.geoServer}${layerInfo.craft}%3A${layerInfo.cellId}_${layerInfo.type}@EPSG%3A900913@png/{z}/{x}/{y}.png`
        ],
        tileSize: 256,
      })
      maps.map.addLayer({
        id: `${layerInfo.type}`,
        type: "raster",
        source: `${layerInfo.type}`,
        paint: {
          "raster-opacity": 1,
        },
      })
    }

    // 读取边界数据
    const readBorderFile = (cellId:number)=>{
      let inputDOM: any = document.getElementById("uploadBorderFile")
      let files = inputDOM.files

      if (files[0]) {
        let reader = new FileReader();
        reader.readAsText(files[0], "UTF-8");
        reader.onload = (e: any)=>{
          try{
            let fileStr = e.target.result
            let fileStrArr = fileStr.split(",,")

            coordinateTypeFormState.value.cellId = cellId
            coordinateTypeFormState.value.count = 0
            coordinateTypeFormState.value.first = new Array()
            coordinateTypeFormState.value.second = new Array()

            for (let i = 0; i < fileStrArr.length; i++) {
              let pointArr = fileStrArr[i].split(",")
              if (pointArr.length == 2) {
                coordinateTypeFormState.value.count++
                coordinateTypeFormState.value.first.push(parseFloat(pointArr[0]))
                coordinateTypeFormState.value.second.push(parseFloat(pointArr[1]))
              }
            }
            setBorder(coordinateType.value,(res:any)=>{
              if(res.data.count>=3){
                let minX = res.data.second[0]
                let maxX = res.data.second[0]
                let minY = res.data.first[0]
                let maxY = res.data.first[0]
                for (let i= 0; i< res.data.count; i++){
                  minX = minX > res.data.second[i] ? res.data.second[i] : minX
                  maxX = maxX < res.data.second[i] ? res.data.second[i] : maxX
                  minY = minY > res.data.first[i] ? res.data.first[i] : minY
                  maxY = maxY < res.data.first[i] ? res.data.first[i] : maxY
                }
                if(maps.map) {
                  maps.map.setZoom(16)
                  maps.map.jumpTo({center: new mapboxgl.LngLat((minY+maxY)/2, (minX+maxX)/2)})
                }
              }
            })
          }catch (e){
            message.warn("导入格式错误")
          }
        }
        inputDOM.value = "";
      }
    }

    // 获取边界
    const getBorder = (type:number = 1,cellId:number,callback:Function|null)=>{
      let url = type==1?"/common/findCellBorderByCellIdAB":"/common/findCellBorderByCellId"
      axios.post(url,
          {cellId:cellId}).then((res:any)=>{
        if(res.success){
          border.abBorder = new Array()
          border.wgsBorder = new Array()
          let borderList = new Array()
          for (let i = 0; i < res.data.borderCount; i++) {
            borderList.push({
              lon:res.data.first[i],
              lat:res.data.second[i],
            })
          }
          if(type == 1){
            border.abBorder = borderList
          }else if(type == 2){
            border.wgsBorder = borderList
          }
          if(callback) callback(res)
        }else{
          message.info(res.msg)
        }
      })
    }

    // 设置边界
    const setBorder = (type:number=1,callback:Function|null=null)=>{
      let url = type==1?"/common/updateCellBorderByCellIdAB":"/common/updateCellBorderByCellId"
      axios.post(url,
          coordinateTypeFormState.value).then((res1:any)=>{
        if(res1.success){
          createTiledMap(coordinateTypeFormState.value.cellId).then((res2:any)=>{
            if(res2&&callback){
              callback(res1)
            }
            if(!res2) message.info("生成瓦片图失败")
          })
          message.info("导入成功")
        }else{
          message.info(res1.msg)
        }
      })
    }

    // 绘制边界瓦片
    const createTiledMap = (cellId:number)=>{
      return new Promise((resolve,reject)=>{
        axios.post("/nyMap/reCreatBorder",
            qs.stringify({
              cellID:cellId
            }),{
              headers: {'Content-Type': 'application/x-www-form-urlencoded'}
            }).then((res:any)=>{
              axios.post("/nyMap/reCreatReport",
                  qs.stringify({
                    cellID:cellId,
                    workType:1,
                  }),{
                    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
                  })
              axios.post("/nyMap/reCreatReport",
                  qs.stringify({
                    cellID:cellId,
                    workType:2,
                  }),{
                    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
                  })
              resolve(res.success)
            })
      })
    }

    watch(()=>props.cellInfo,(newValue,oldValue)=>{
      setTimeout(()=>{
        getNorm(newValue.cellId)
        addBorderLayer(newValue.cellId)
        getBorder(2,newValue.cellId,(res:any)=>{
          if(res.data.borderCount>=3){
            let minX = res.data.second[0]
            let maxX = res.data.second[0]
            let minY = res.data.first[0]
            let maxY = res.data.first[0]
            for (let i= 0; i< res.data.borderCount; i++){
              minX = minX > res.data.second[i] ? res.data.second[i] : minX
              maxX = maxX < res.data.second[i] ? res.data.second[i] : maxX
              minY = minY > res.data.first[i] ? res.data.first[i] : minY
              maxY = maxY < res.data.first[i] ? res.data.first[i] : maxY
            }
            if(maps.map) {
              maps.map.setZoom(16)
              maps.map.jumpTo({center: new mapboxgl.LngLat((minY+maxY)/2, (minX+maxX)/2)})
            }
          }
        })
        compactionType.value = props.cellInfo.kind
      },500)
    },{immediate: true})

    onMounted(()=>{
      initMap()
    })

    onBeforeUnmount(()=>{
      maps.map.remove()
    })

    return {
      showBorderModal,
      coordinateType,
      compactionType,

      KindEnum,
      coordinateDict,
      CompactionDict,
      readBorderFile,
      openFileModal,
      ...toRefs(border),
      getBorder,

      norm,
      addVNorm,
      removeNorm,
      setNorm
    }
  },
  props: {
    isShow: {
      type: Boolean,
      default: false
    },
    cellInfo: {
      type: Object,
      default: null
    }
  },
  components:{DeleteOutlined,SModal}
})
</script>

<style lang="scss" scoped>
.map-box{
  position: relative;
  flex: 1;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  #mapboxgl-box{
    display: flex;
    width: 100%;
    height: calc(100% - 6px);
    box-sizing: border-box;
  }
}
.form-box{
  display: flex;
  flex-direction: column;
  margin-top: 20px;
  width: 100%;
  height: 460px;
  padding: 18px 30px 10px 30px;
  box-sizing: border-box;
  .set-header{
    font-size: 18px;
    font-weight: bold;
    color: #333333;
    padding-bottom: 10px;
    border-bottom: 1px solid #EDF0FB;
  }
  .set-form{
    flex: 1;
    width: 100%;
    >span{
      display: block;
      padding: 12px 0px 5px;
      font-size: 16px;
      font-weight: bold;
      color: #333333;
    }
    ::v-deep >.ant-form .ant-input-number{
      width: 128px;
    }
    ::v-deep >.ant-form >span{
      display: inline-block;
      width: 100%;
      padding: 8px 0 4px;
      color: #333333;
      font-size: 16px;
      font-weight: bold;
    }
    ::v-deep .ant-select{
      width: 177px;
    }
    ::v-deep label{
      color: #666666;
    }
    ::v-deep .button-box{
      float: right;
      button{
        margin-left: 8px;
      }
    }
    .right-item{
      float: right;
      ::v-deep button{
        margin-left: 18px;
      }
    }
  }
}
.cv-norm-box{
  .button-box{
    display: flex;
    justify-content: flex-end;
    width: 100%;
    height: 60px;
    padding-top: 14px;
    padding-right: 16px;
    box-sizing: border-box;
  }
}
</style>
